home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / et / et3_0-a1.lha / et3 / src / Env.C < prev    next >
C/C++ Source or Header  |  1992-06-18  |  8KB  |  430 lines

  1. #ifdef __GNUG__
  2. #pragma implementation
  3. #endif
  4.  
  5. #include "Env.h"
  6.  
  7. #include "Class.h"
  8. #include "String.h"
  9. #include "System.h"
  10. #include "OrdColl.h"
  11. #include "StreamBuf.h"
  12. #include "CLib.h"
  13.  
  14. //---- EnvParser ---------------------------------------------------------------
  15.  
  16. class EnvParser {
  17.     FILE *ifp;
  18. public:
  19.     EnvParser(FILE *f)
  20.     { ifp= f; }
  21.     virtual void KeyValue(char*, char*, char*)
  22.     { }
  23.     virtual void Char(int)
  24.     { }
  25.     void Parse();
  26. };
  27.  
  28. void EnvParser::Parse()
  29. {
  30.     char name[200], type[200], value[200];
  31.     int c, state= 0, ni, ti, vi;
  32.     
  33.     ni= ti= vi= 0;
  34.  
  35.     while ((c= fgetc(ifp)) != EOF) {
  36.     if (c == '\n') {
  37.         state= 0;
  38.         if (ni > 0) {
  39.         name[ni++]= 0;
  40.         type[ti++]= 0;
  41.         value[vi++]= 0;
  42.         ni= ti= vi= 0;
  43.         KeyValue(name, value, type);
  44.         }
  45.         Char(c);
  46.         continue;
  47.     }
  48.     switch (state) {
  49.     case 0:             // start of line 
  50.         switch (c) {
  51.         case ' ':
  52.         case '\t':
  53.         break;
  54.         case '#':
  55.         state= 1;
  56.         break;
  57.         default:
  58.         state= 2;
  59.         break;
  60.         }
  61.         break;
  62.  
  63.     case 1:             // comment
  64.         break;
  65.  
  66.     case 2:             // name
  67.         switch (c) {
  68.         case ' ':
  69.         case '\t':
  70.         case ':':
  71.         state= 3;
  72.         break;
  73.         case '(':
  74.         state= 7;
  75.         break;
  76.         default:
  77.         break;
  78.         }
  79.         break;
  80.         
  81.     case 3:             // ws before value
  82.         if (c != ' ' && c != '\t')
  83.         state= 4;
  84.         break;
  85.  
  86.     case 4:             // value
  87.         break;
  88.  
  89.     case 5:             // type
  90.         if (c == ')')
  91.         state= 6;
  92.         break;
  93.  
  94.     case 6:             // optional ':'
  95.         state= (c == ':') ? 3 : 4;
  96.         break;
  97.  
  98.     case 7:
  99.         state= (c == ')') ? 6 : 5;
  100.         break;
  101.  
  102.     }
  103.     switch (state) {
  104.     case 2:
  105.         name[ni++]= c;
  106.         break;
  107.     case 4:
  108.         value[vi++]= c;
  109.         break;
  110.     case 5:
  111.         type[ti++]= c;
  112.         break;
  113.     }
  114.     if (state != 4)
  115.         Char(c);
  116.     }
  117. }
  118.  
  119. //---- ReadEnvParser -----------------------------------------------------------
  120.  
  121. class ReadEnvParser: public EnvParser {
  122.     EnvLevel level;
  123. public:
  124.     ReadEnvParser(FILE *f, EnvLevel l) : EnvParser(f)
  125.     { level= l; }
  126.     void KeyValue(char *name, char *value, char *type)
  127.     { Env::SetValue(name, value, level, type); }
  128. };
  129.  
  130. //---- WriteEnvParser ----------------------------------------------------------
  131.  
  132. class WriteEnvParser: public EnvParser {
  133.     FILE *ofp;
  134. public:
  135.     WriteEnvParser(FILE *f, FILE *of) : EnvParser(f)
  136.     { ofp= of;  }
  137.     void KeyValue(char *name, char *value, char *type);
  138.     void Char(int c)
  139.     { fputc(c, ofp); }
  140. };
  141.  
  142. void WriteEnvParser::KeyValue(char *name, char *value, char*)
  143. {
  144.     EnvRec *er= Env::Lookup(name);
  145.     if (er && er->changed) {
  146.     er->changed= FALSE;
  147.     if (er->op)
  148.         er->Write(er->op);
  149.     if (er->op2)
  150.         er->Write2(er->op);
  151.     fprintf(ofp, "%s", er->value);
  152.     } else
  153.     fprintf(ofp, "%s", value);
  154. }
  155.  
  156. //---- EnvRec ------------------------------------------------------------------
  157.  
  158. NewMetaImpl(EnvRec,Object, (T(name), TS(value), TS(type), TE(level), TB(changed)));
  159.  
  160. EnvRec::EnvRec(Symbol n, char *v, char *t, EnvLevel l)
  161. {
  162.     name= n;
  163.     value= strsave(v);
  164.     level= l;
  165.     if (t)
  166.     type= strsave(t);
  167.     else
  168.     type= 0;
  169.     changed= (l == eEnvChange);
  170.     op= 0;
  171. }
  172.  
  173. EnvRec::~EnvRec()
  174. {
  175.     SafeDelete(value);
  176.     SafeDelete(type);
  177. }
  178.  
  179. void EnvRec::Read(Object *op)
  180. {
  181.     IStream is(strlen(value), value);
  182.     op->ReadFrom(is);
  183. }
  184.  
  185. Object *EnvRec::Read2()
  186. {
  187.     Object *op= 0;
  188.     IStream is(strlen(value), value);
  189.     is >> op;
  190.     return op;
  191. }
  192.  
  193. void EnvRec::Write(Object *op)
  194. {
  195.     char *cp= new char[1000];
  196.     OStream os(1000, cp);
  197.     op->PrintOn(os);
  198.     ChangeValue(cp, 0, eEnvChange);
  199.     delete cp;
  200. }
  201.  
  202. void EnvRec::Write2(Object*)
  203. {
  204. }
  205.  
  206. void EnvRec::ChangeValue(char *v, char*, EnvLevel l)
  207. {
  208.     if (l != eEnvChange && level == l) {
  209.     fprintf(stderr,
  210.     "EnvRec::ChangeValue: duplicate entry <%s=%s> for level %d; ignored\n",
  211.                             name.AsString(), v, l);
  212.     return;
  213.     }
  214.     if (strcmp(value, v) != 0) {
  215.     if (l == eEnvChange)
  216.         changed= TRUE;
  217.     else {
  218.         changed= FALSE;
  219.         level= l;
  220.     }
  221.     strreplace(&value, v);
  222.     if (changed && op)
  223.         Read(op);
  224.     }
  225. }
  226.  
  227. void EnvRec::InspectorId(char *buf, int bufSize)
  228. {
  229.     strn0cpy(buf, name.AsString(), bufSize);
  230. }
  231.  
  232. int EnvRec::Compare(Object *op)
  233. {
  234.     return StrCmp((byte*)name.AsString(),
  235.           (byte*)Guard(op,EnvRec)->name.AsString(), -1, sortmap);
  236. }
  237.  
  238. //---- EnvRec ------------------------------------------------------------------
  239.  
  240. NewMetaImpl(Env,Object, (TP(table), TB(terminated)));
  241.  
  242. static Env gEnv;
  243.  
  244. OrdCollection *Env::table;
  245. bool Env::terminated;
  246.  
  247. Env::Env()
  248. {
  249. }
  250.  
  251. Env::~Env()
  252. {
  253.     terminated= TRUE;
  254.     if (table) {
  255.     table->FreeAll();
  256.     SafeDelete(table);
  257.     }
  258. }
  259.  
  260. void Env::Init()
  261. {
  262.     if (table)
  263.     return;
  264.     
  265.     table= new OrdCollection;
  266.  
  267.     ReadFile(form("%s/ETRC", gEtDir), eEnvGlobal);
  268.     ReadFile(form("%s/ETRC", gSystem->HomeDirectory()), eEnvUser);
  269.     ReadFile("ETRC", eEnvLocal);
  270.     
  271.     for (int i= 0; CLib::Environ[i]; i++)
  272.     SetValue(CLib::Environ[i], eEnvEnvironment);
  273. }
  274.  
  275. EnvRec *Env::Lookup(char *n)
  276. {
  277.     if (table == 0)
  278.     Env::Init();
  279.     u_int name;
  280.     if (name= SymbolTable::Lookup(n)) {
  281.     Iter next(table);
  282.     EnvRec *er;
  283.     
  284.     while (er= (EnvRec*) next())
  285.         if (er->name.Id() == name)
  286.         return er;
  287.     }
  288.     return 0;
  289. }
  290.  
  291. //---- Loading/Storing ---------------------------------------------------------
  292.  
  293. void Env::ReadFile(char *fname, EnvLevel level)
  294. {
  295.     FILE *ifp;
  296.     if (ifp= fopen(fname, "r")) {
  297.     ReadEnvParser rp(ifp, level);
  298.     rp.Parse();
  299.     fclose(ifp);
  300.     }
  301. }
  302.  
  303. void Env::Save()
  304. {
  305.     FILE *ifp, *ofp;
  306.     
  307.     if (ofp= fopen(form("%s/ETRC.new", gSystem->HomeDirectory()), "w")) {
  308.     if (ifp= fopen(form("%s/ETRC", gSystem->HomeDirectory()), "r")) {
  309.         WriteEnvParser wp(ifp, ofp);
  310.         wp.Parse();
  311.  
  312.         Iter next(table);
  313.         EnvRec *er;
  314.         while (er= (EnvRec*) next())
  315.         if (er->changed) {
  316.             er->changed= FALSE;
  317.             fprintf(ofp, "%s %s\n", er->name.AsString(), er->value);
  318.         }
  319.         fclose(ifp);
  320.         fclose(ofp);
  321.         gSystem->Rename(form("%s/ETRC", gSystem->HomeDirectory()),
  322.                 form("%s/ETRC.BAK", gSystem->HomeDirectory()));
  323.         gSystem->Rename(form("%s/ETRC.new", gSystem->HomeDirectory()),
  324.                 form("%s/ETRC", gSystem->HomeDirectory()));
  325.         return;
  326.     }
  327.     fclose(ofp);
  328.     }
  329. }
  330.  
  331. //---- GetValue ----------------------------------------------------------------
  332.  
  333. char *Env::getvalue(char *name)
  334. {
  335.     if (terminated)
  336.     return 0;
  337.     EnvRec *er= Lookup(form("%s.%s", gProgname, name));
  338.     if (er == 0)
  339.     er= Lookup(form("*.%s", name));
  340.     if (er == 0)
  341.     er= Lookup(name);
  342.     if (er == 0)
  343.     return 0;
  344.     return er->value;
  345. }
  346.  
  347. int Env::GetValue(char *name, int dflt)
  348. {
  349.     char *cp= Env::getvalue(name);
  350.     if (cp) {
  351.     int n;
  352.     if (sscanf(cp, "%d", &n) == 1)
  353.         return n;
  354.     if (strcmp(cp, "TRUE") == 0 || strcmp(cp, "ON") == 0
  355.                             || strcmp(cp, "YES") == 0)
  356.         return 1;
  357.     if (strcmp(cp, "FALSE") == 0 || strcmp(cp, "OFF") == 0
  358.                             || strcmp(cp, "NO") == 0)
  359.         return FALSE;
  360.     }
  361.     return dflt;
  362. }
  363.  
  364. char *Env::GetValue(char *name, char *dflt)
  365. {
  366.     char *cp= Env::getvalue(name);
  367.     if (cp)
  368.     return cp;
  369.     return dflt;
  370. }
  371.  
  372. //---- SetValue ----------------------------------------------------------------
  373.  
  374. void Env::SetValue(char *name, char *value, EnvLevel level, char *type)
  375. {
  376.     if (table == 0)
  377.     Env::Init();
  378.     
  379.     EnvRec *er= Lookup(name);
  380.     if (er)
  381.     er->ChangeValue(value, type, level);
  382.     else
  383.     table->Add(new EnvRec(name, value, type, level));
  384. }
  385.  
  386. void Env::SetValue(char *name, EnvLevel level)
  387. {
  388.     char *buf= strsave(name), *cp;
  389.     if (cp= strchr(buf, '=')) {
  390.     *cp++= 0;
  391.     SetValue(buf, cp, level);
  392.     } else
  393.     SetValue(name, "1", level);
  394.     delete buf;
  395. }
  396.  
  397. void Env::SetValue(char *name, int value)
  398. {
  399.     SetValue(name, form("%d", value));
  400. }
  401.  
  402. void Env::SetValue(char *name, double value)
  403. {
  404.     SetValue(name, form("%f", value));
  405. }
  406.  
  407. void Env::SetBoolValue(char *name, bool value)
  408. {
  409.     SetValue(name, value ? "TRUE" : "FALSE");
  410. }
  411.  
  412. //---- Bind --------------------------------------------------------------------
  413.  
  414. bool Env::Bind(Object *&op, char *name)
  415. {
  416.     EnvRec *er= Lookup(form("%s.%s", gProgname, name));
  417.     if (er == 0)
  418.     er= Lookup(form("*.%s", name));
  419.     if (er == 0)
  420.     er= Lookup(name);
  421.     
  422.     if (er) {
  423.     er->op= op;
  424.     er->Read(op);
  425.     return TRUE;
  426.     }
  427.     return FALSE;
  428. }
  429.  
  430.